/**************************************************************************//**
 * @item     CosyOS-II Kernel
 * @file     os_api.c
 * @brief    内核服务公共函数
 * @details  在服务层临界区中，由内核服务调用。
 * @author   迟凯峰
 * @version  V3.2.0
 * @date     2024.12.13
 ******************************************************************************/

#include "os_var.h"

#if SYSCFG_MCUCORE == 8051
#pragma NOAREGS /* 相对寄存器访问 for C51 */
#endif

/**
 \brief      任务优先级切换
 \details    如果该任务的优先级高于当前任务的优先级，立即切换任务。
 \param[in]  htask     任务句柄
 \return     无
 \note       直接关联服务（非滴答中）：切换任务、恢复指定任务并挂起自身任务、设置阻塞（时间）、清除阻塞（状态）。
 */
void s_switch_taskpri(s_tasknode_tsp htask)
{
	if(htask->pri > s_task_current->pri){
		if(s_task_switch == OS_NULL){
			s_task_switch = htask;
			s_sign_schedule = true;
		}
		else if(htask->pri > s_task_switch->pri){
			s_task_switch = htask;
			s_sign_switch_prigroup = false;
		}
		else if(htask->pri == s_task_switch->pri){
			s_sign_switch_prigroup = true;
		}
	}
}

/**
 \brief      非空切换
 \details    当任务非空时，实行任务优先级切换。
 \param[in]  htask     任务句柄
 \return     无
 \note       关联服务（非滴答中）：给予/归还二值信号量、给予/归还计数信号量、发送飞信、发送邮件、发送消息。
 */
void s_switch_notnull(s_tasknode_tsp htask)
{
	if(htask != OS_NULL){
		s_switch_taskpri(htask);
	}
}

/**
 \brief      就绪切换
 \details    当任务状态为就绪时，实行任务优先级切换。
 \param[in]  htask     任务句柄
 \return     无
 \note       关联服务（非滴答中）：恢复任务。
 */
void s_switch_ready(s_tasknode_tsp htask)
{
	if(htask->status == OS_STATUS_READY){
		s_switch_taskpri(htask);
	}
}

#if SYSCFG_TASKMSG == __ENABLED__
/**
 \brief      私信切换
 \details    当任务阻塞类型为接收私信阻塞时，实行任务优先级切换。
 \param[in]  htask     任务句柄
 \return     无
 \note       关联服务（非滴答中）：发送私信。
 */
void s_switch_taskmsg(s_tasknode_tsp htask)
{
	if(htask->blocktype & OS_BLOCKED_TASKMSG){
		s_switch_taskpri(htask);
	}
}
#endif

/**
 \brief      设置任务优先级
 \details    从任务队列中移除该任务并加入临时链表。
 \param[in]  htask     任务句柄
 \return     无
 \note       关联服务：设置任务优先级、获取互斥信号量、归还互斥信号量。
 */
void s_set_taskpri(s_tasknode_tsp htask)
{
	htask->last->next = htask->next;
	htask->next->last = htask->last;
	htask->next = htask->last = OS_NULL;
	if(s_taskpri_tail != OS_NULL){
		s_taskpri_tail->next = htask;
		htask->last = s_taskpri_tail;
	}
	s_taskpri_tail = htask;
	s_sign_schedule_all = true;
}

#if SYSCFG_GETRTC_INT == __ENABLED__
/**
 \brief      更新RTC副本
 \param      无
 \return     无
 */
void s_update_rtccopy(void)
{
	s_sign_updatecopy = true;
	#if SYSCFG_MCUCORE == 8051
	s_rtc_copy.yeah   = s_rtc.yeah;
	s_rtc_copy.year   = s_rtc.year;
	s_rtc_copy.month  = s_rtc.month;
	s_rtc_copy.date   = s_rtc.date;
	s_rtc_copy.hour   = s_rtc.hour;
	s_rtc_copy.minute = s_rtc.minute;
	s_rtc_copy.second = s_rtc.second;
	s_rtc_copy.day    = s_rtc.day;
	#else
	s_rtc_copy = s_rtc;
	#endif
	s_sign_updatecopy = false;
}
#endif
